import { useCallback, useState } from 'react'
import { createEditor,Editor,Transforms,Element as SlateElement,Range } from 'slate'
import type {Descendant} from 'slate'
import { isKeyHotkey } from 'is-hotkey'
import isUrl from 'is-url'

import { Slate, Editable,  withReact } from 'slate-react'
import {ColorPicker,Button,Space, Select} from 'antd'
import { Color } from 'antd/es/color-picker'

const initialValue = [
  {
    type: 'paragraph',
    children: [{ text: 'A line of text in a paragraph.' }],
  },
  {
    type: 'block-quote',
    children: [{ text: 'A wise quote.' }],
  },
]
const InlineChromiumBugfix = () => (
  <span
    contentEditable={false}
    style={{'fontSize':0}}
  >
    {String.fromCodePoint(160) /* Non-breaking space */}
  </span>
)

const wrapLink=(editor,value)=>{
  
  
   if(isLinkActive(editor)){
    Transforms.unwrapNodes(editor, {
      match: n =>
        !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',
    })
   }
 
   const {selection} = editor;  
   const isCollapsed = selection && Range.isCollapsed(selection)
   console.log("isCollapsed",isCollapsed)
   const link= { type: 'link', url:value,children: isCollapsed ? [{ text: value }] : []}
    if(isCollapsed){
      Transforms.insertNodes(editor, link)

    }else{

      console.log("wrapNodes=====>",link)
      Transforms.wrapNodes(  
        editor,  
        link,
        { split: true }  
      );
      Transforms.collapse(editor, { edge: 'end' })

    }
     return;
  
}
const isLinkActive = editor => {
  const [link] = Editor.nodes(editor, {
    match: n =>
      !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',
  })
  return !!link
}
const withInlines = editor => {
  const { insertData, insertText, isInline, isElementReadOnly, isSelectable } =
    editor

  editor.isInline = element =>
    ['link', 'button', 'badge'].includes(element?.type) || isInline(element)



    
  return editor
}

const Leaf = ({ attributes, children, leaf }) => {
  const styles:any={}
   
   Object.keys(leaf).forEach(key=>{
       if(/^style-/.test(key)){
          let styleKey=key?.split('style-')?.[1]
        if(/[a-zA-Z0-9]*\.[a-zA-Z0-9-]*$/.test(styleKey)){
         const [,key1,key2]=/([a-zA-Z0-9-].*)\.([a-zA-Z0-9-].*)$/g.exec(styleKey);
          if(styles[key1]){
            styles[key1]=`${styles[key1]} ${key2}`
          }else{
            styles[key1]=key2
          }
        }else{
          styles[styleKey]=leaf[key]
        }
         
       } 
  })
  if(Object.keys(styles)?.length){
    return <span {...attributes} style={{...styles,'paddingLeft':leaf.text === ''?'0.1px':undefined}} >{children}</span>
  }  
 
  return <span {...attributes} style={{'paddingLeft':leaf.text === ''?'0.1px':undefined}}>{children}</span>
}

const ElementRender = ({ attributes, children, element }) => {
  const style = { textAlign: element?.['style-textAlign'] }
  console.log("ElementRender===>",element)
  switch (element.type) {
    case 'block-quote':
      return (
        <blockquote style={style} {...attributes}>
          {children}
        </blockquote>
      )
    case 'bulleted-list':
      return (
        <ul style={style} {...attributes}>
          {children}
        </ul>
      )
      case 'link':
        return (
          <a  {...attributes} style={style} href={element?.url}>
            {children}
          </a>
        )
    case 'list-item':
      return (
        <li style={style} {...attributes}>
          {children}
        </li>
      )
    case 'numbered-list':
      return (
        <ol style={style} {...attributes}>
          {children}
        </ol>
      )
    default:
      return (
        <p style={style} {...attributes}>
          {children}
        </p>
      )
  }
}
const BLOCK_NODE=['style-textAlign','numbered-list','bulleted-list','h1','h2','h3','h4','h5','h6'];
const LIST_TYPES=['numbered-list','bulleted-list','h1','h2','h3','h4','h5','h6']
const TEXT_ALIGN_TYPES=['style-textAlign']
const App = () => {
  const [editor] = useState(() => withInlines(withReact((createEditor()))))
  const [hexColor,setHexColor] = useState<string>('#000000');
  const renderLeaf = useCallback((props: any) => <Leaf {...props} />, [])
  const renderElement = useCallback(props => <ElementRender {...props} />, [])

  const onChangeComplete=(value: Color)=>{
    const color=typeof value === 'string' ? value : value?.toHexString();
    setHexColor(color)
    Editor.addMark(editor,'style-color',color)

  }

  const onChange=(value:Descendant[])=>{
    console.log(value)
  }
  const isMarkActive = (editor, format,value) => {
    const marks = Editor.marks(editor)
    return marks?.[format]&&marks?.[format]===value
  }
  const isBlockActive = (editor, format,blockType ) => {
    const { selection } = editor
    if (!selection) return false
  
    const [match] = Array.from(
      Editor.nodes(editor, {
        at: Editor.unhangRange(editor, selection),
        match:(n)=>{
          console.log( n?.[blockType]===format,blockType,format,n,n?.isBlock?.())
        return   !Editor.isEditor(n)&&SlateElement.isElement(n)&&(n?.[blockType]===format);
        }
         
      })
    )
    return !!match
  }

  const onFormat=(format:string,value:string)=>{
    // Transforms.unwrapNodes(editor, {
    //   match: n =>
    //     !Editor.isEditor(n) &&
    //     SlateElement.isElement(n) &&
    //     !['center'].includes(format),
    //   split: true,
    // })
 
    if(BLOCK_NODE.includes(format)){
      const key=LIST_TYPES.includes(format)?'type':format;

      const isActive=isBlockActive(editor,format,key)
      Transforms.unwrapNodes(editor, {
        match: n =>
          !Editor.isEditor(n) &&
          SlateElement.isElement(n) &&
          LIST_TYPES.includes(n.type) &&
          !TEXT_ALIGN_TYPES.includes(format),
        split: true,
      })
    
      Transforms.setNodes(editor,{
        [key]:key==='type'?isActive?'paragraph':'list-item':isActive?undefined:value
     })
    if (!isActive && LIST_TYPES.includes(format)) {
      const block = { type: format, children: [] }
      Transforms.wrapNodes(editor, block)
    }
      return;
    }
    if(isMarkActive(editor,format,value)){
      Editor.removeMark(editor,format)
    }else{
      Editor.addMark(editor,format,value)
    }
  }

  const handleChange=(value: string, option: { value: string; label: string; disabled?: undefined } )=> {
  onFormat('style-fontSize',`${value}px`)
   
  }
  const insertLink = (editor, url) => {
    if (editor.selection) {
      wrapLink(editor, url)
    }
  }



  return (
    <Slate editor={editor} initialValue={initialValue} onChange={onChange}>
    <Space>  
      <Button size="small" onClick={()=>onFormat('style-fontWeight','bold')}>B</Button>
      <Button size="small" onClick={()=>onFormat('style-fontStyle','italic')}>italic</Button>
      <Button size="small" onClick={()=>onFormat('style-textDecoration.underline','underline')}>underline</Button>
      <Button size="small" onClick={()=>onFormat('style-textDecoration.line-through','line-through')}>line-through</Button>
      <Button size="small" onClick={()=>onFormat('style-textAlign','center')}>center</Button>
      <Button size="small" onClick={()=>onFormat('style-textAlign','left')}>left</Button>
      <Button size="small" onClick={()=>onFormat('style-textAlign','right')}>right</Button>
      <Button size="small" onClick={()=>onFormat('numbered-list','numbered-list')}>numbered-list</Button>
      <Button size="small" onClick={()=>onFormat('bulleted-list','bulleted-list')}>bulleted-list</Button>
      <Button size="small" onClick={()=>insertLink(editor,'url|text')}>link</Button>
      <Select
      defaultValue="12"
      style={{ width: 120 }}
      onChange={handleChange}
      options={[
        { value: '12', label: 'T12' },
        { value: '14', label: 'T14' },
        { value: '16', label: 'T16' },
        { value: '18', label: 'T18' },
        { value: '24', label: 'T24' },
        { value: '32', label: 'T32' },
     
      ]}
    />
      <Select
      defaultValue="12"
      style={{ width: 120 }}
      onChange={handleChange}
      options={[
        { value: '12', label: 'T12' },
        { value: '14', label: 'T14' },
        { value: '16', label: 'T16' },
        { value: '18', label: 'T18' },
        { value: '24', label: 'T24' },
        { value: '32', label: 'T32' },
     
      ]}
    />
    <ColorPicker defaultFormat='hex' format="hex"  size="small" onChange={onChangeComplete}/>{hexColor}</Space>
eqweqwewq
    </Slate>
  )
}
export default App